<!DOCTYPE html>
<html lang="zh_cn">
<head>
          <title>来玩魔王的咚</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta charset="utf-8" />
        <!-- twitter card metadata -->
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="/images/mowang.png">
<meta name="twitter:site" content="">
<meta name="twitter:title" content="Python collections 模块">
<meta name="twitter:description" content="<p>namedtuple具名元组；defaultdict有默认值的字典类型，setdefault方法也可以设置默认值；Counter字典实现的计数器（多重集合）；其他映射类型。</p>">
        <!-- OG Tags -->
<meta property="og:url" content="/python-moudle-collections.html"/>
<meta property="og:title" content="来玩魔王的咚 | Python collections 模块" />
<meta property="og:description" content="<p>namedtuple具名元组；defaultdict有默认值的字典类型，setdefault方法也可以设置默认值；Counter字典实现的计数器（多重集合）；其他映射类型。</p>" />
        <!-- favicon -->
        <link rel="icon" type="image/png" href="/images/mowang.png">
        <!-- moment.js for date formatting -->
        <script src="/theme/js/moment.js"></script>
        <!-- css -->
        <link rel="stylesheet" type="text/css" href="/theme/css/main.css" />
        <!-- 左边的menu，如果页面高度不够，就跟着滚动，否则文章分类显示不全 -->
        <link rel="stylesheet" type="text/css" href="/theme/css/mycss/menu.css" />
		<script>
			
                /*! grunt-grunticon Stylesheet Loader - v2.1.2 | https://github.com/filamentgroup/grunticon | (c) 2015 Scott Jehl, Filament Group, Inc. | MIT license. */
    
    (function(e){function t(t,n,r,o){"use strict";function a(){for(var e,n=0;u.length>n;n++)u[n].href&&u[n].href.indexOf(t)>-1&&(e=!0);e?i.media=r||"all":setTimeout(a)}var i=e.document.createElement("link"),l=n||e.document.getElementsByTagName("script")[0],u=e.document.styleSheets;return i.rel="stylesheet",i.href=t,i.media="only x",i.onload=o||null,l.parentNode.insertBefore(i,l),a(),i}var n=function(r,o){"use strict";if(r&&3===r.length){var a=e.navigator,i=e.Image,l=!(!document.createElementNS||!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect||!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image","1.1")||e.opera&&-1===a.userAgent.indexOf("Chrome")||-1!==a.userAgent.indexOf("Series40")),u=new i;u.onerror=function(){n.method="png",n.href=r[2],t(r[2])},u.onload=function(){var e=1===u.width&&1===u.height,a=r[e&&l?0:e?1:2];n.method=e&&l?"svg":e?"datapng":"png",n.href=a,t(a,null,null,o)},u.src="",document.documentElement.className+=" grunticon"}};n.loadCSS=t,e.grunticon=n})(this);(function(e,t){"use strict";var n=t.document,r="grunticon:",o=function(e){if(n.attachEvent?"complete"===n.readyState:"loading"!==n.readyState)e();else{var t=!1;n.addEventListener("readystatechange",function(){t||(t=!0,e())},!1)}},a=function(e){return t.document.querySelector('link[href$="'+e+'"]')},c=function(e){var t,n,o,a,c,i,u={};if(t=e.sheet,!t)return u;n=t.cssRules?t.cssRules:t.rules;for(var l=0;n.length>l;l++)o=n[l].cssText,a=r+n[l].selectorText,c=o.split(");")[0].match(/US\-ASCII\,([^"']+)/),c&&c[1]&&(i=decodeURIComponent(c[1]),u[a]=i);return u},i=function(e){var t,o,a;o="data-grunticon-embed";for(var c in e)if(a=c.slice(r.length),t=n.querySelectorAll(a+"["+o+"]"),t.length)for(var i=0;t.length>i;i++)t[i].innerHTML=e[c],t[i].style.backgroundImage="none",t[i].removeAttribute(o);return t},u=function(t){"svg"===e.method&&o(function(){i(c(a(e.href))),"function"==typeof t&&t()})};e.embedIcons=i,e.getCSS=a,e.getIcons=c,e.ready=o,e.svgLoadedCallback=u,e.embedSVG=u})(grunticon,this);
                
                grunticon(["/theme/css/icons.data.svg.css", "/theme/css/icons.data.png.css", "/theme/css/icons.fallback.css"]);
            </script>
        <noscript><link href="/theme/css/icons.fallback.css" rel="stylesheet"></noscript>
        <!-- menu toggle javascript -->
        <script type="text/javascript">
            document.addEventListener("DOMContentLoaded", initMenu);
            
            function initMenu(){
                var menu = document.getElementById("menu");
                var menulink = document.getElementById("menu-link");
                menulink.addEventListener("click", function toggleMenu(){
                        window.event.preventDefault();
                        menulink.classList.toggle('active');
                        menu.classList.toggle('active');              
                    });
            };
        </script>
        <!-- 不蒜子 -->
        <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

    <meta name="description" content="<p>namedtuple具名元组；defaultdict有默认值的字典类型，setdefault方法也可以设置默认值；Counter字典实现的计数器（多重集合）；其他映射类型。</p>" />

    <meta name="tags" content="python模块" />
  <!-- 替换部分base的样式，看文章时，要再宽一点，右边有很多空间可以撑开 -->
  <link rel="stylesheet" type="text/css" href="/theme/css/mycss/article.css" />

</head>
<body>
    <div role="banner" id="masthead">
        <header>
            <a href="/"><img src="/images/mowang.png" alt="McManus Logo"></a>
                <h1>来玩魔王的咚@骑士救兵</h1>
            <a href="#menu" id="menu-link">more stuff</a>
            <nav id="menu">
                <ul>
                        <li><a href="/tags">tags</a></li>
                            <li><a href="/category/cloud.html">Cloud</a></li>
                            <li><a href="/category/docker.html">Docker</a></li>
                            <li><a href="/category/go.html">Go</a></li>
                            <li><a href="/category/linux.html">Linux</a></li>
                            <li class="active"><a href="/category/python.html">Python</a></li>
                            <li><a href="/category/xue-xi-bi-ji.html">学习笔记</a></li>
                            <li><a href="/category/yun-wei-zi-dong-hua.html">运维自动化</a></li>
                </ul>
            </nav>
        </header>
    </div>
        <div class="page" role="main">
  <div class="article" role="article">
    <article>
        <footer>
            <a name="top"></a>
            <p>
              <time datetime=" 2020-07-12 13:00:00+08:00">
                <script>document.write(moment('2020-07-12 13:00:00+08:00').format('LL'));</script>
              </time>
              ~
              <time datetime=" 2020-07-12 13:00:00+08:00">
                <script>document.write(moment('2020-07-12 13:00:00+08:00').format('LL'));</script>
              </time>
            </p>
        </footer>
        <header>
          <h2>
            Python collections 模块
          </h2>
        </header>
      <div class="content">
         <div class="toc">
<ul>
<li><a href="#namedtuple-ju-ming-yuan-zu">namedtuple 具名元组</a><ul>
<li><a href="#chuang-jian-ju-ming-yuan-zu">创建具名元组</a></li>
<li><a href="#shi-yong-lei-xing-zhu-jie-yu-fa-chuang-jian-ju-ming-yuan-zu">使用类型注解语法创建具名元组</a></li>
<li><a href="#shu-xing-he-fang-fa">属性和方法</a></li>
<li><a href="#shi-yong-chang-jing">使用场景</a></li>
</ul>
</li>
<li><a href="#defaultdict">defaultdict</a><ul>
<li><a href="#chuang-jian-defaultdict">创建defaultdict</a></li>
<li><a href="#shi-yong-chang-jing_1">使用场景</a></li>
</ul>
</li>
<li><a href="#counter">Counter</a></li>
<li><a href="#qi-ta-lei-xing">其他类型</a></li>
<li><a href="#userdict">UserDict</a></li>
</ul>
</div>
<p>collections模块提供了几种数据类型，使用这些数据类型可以使代码变得更优雅:</p>
<ul>
<li>namedtuple</li>
<li>defaultdict</li>
<li>Counter</li>
</ul>
<h3 id="namedtuple-ju-ming-yuan-zu"><a class="toclink" href="#namedtuple-ju-ming-yuan-zu">namedtuple 具名元组</a></h3>
<p>namedtuple是元组类型的子类，所以本质上它还是一个元组类型，继承了元组所有的特性。<br>
namedtuple同时还解决了元组的一个问题，元祖中的每一个元素都有名字，可以通过名字来访问元组的元素。类似字典，通过key来访问value。  </p>
<h4 id="chuang-jian-ju-ming-yuan-zu"><a class="toclink" href="#chuang-jian-ju-ming-yuan-zu">创建具名元组</a></h4>
<p>创建一个具名元组需要两个参数，一个是类名，另一个是各个字段的名字。字段的名字可以是由字符串组成的可迭代对象，也可以是由空格或逗号分隔的字段名组成的字符串。<br>
示例如下:</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>

<span class="c1"># 使用空格隔开的字符串定义</span>
<span class="n">Student</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s1">&#39;Student&#39;</span><span class="p">,</span> <span class="s1">&#39;name age gender&#39;</span><span class="p">)</span>
<span class="n">s1</span> <span class="o">=</span> <span class="n">Student</span><span class="p">(</span><span class="s1">&#39;小明&#39;</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="s1">&#39;男&#39;</span><span class="p">)</span>
<span class="c1"># 使用字符串的元组定义，列表或者其他可迭代对象都可以</span>
<span class="n">Point</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s1">&#39;Point&#39;</span><span class="p">,</span> <span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">,</span> <span class="s1">&#39;y&#39;</span><span class="p">))</span>
<span class="n">p1</span> <span class="o">=</span> <span class="n">Point</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="mi">11</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="mi">22</span><span class="p">)</span>

<span class="nb">print</span><span class="p">(</span><span class="n">s1</span><span class="p">)</span>  <span class="c1"># Student(name=&#39;小明&#39;, age=14, gender=&#39;男&#39;)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">p1</span><span class="p">)</span>  <span class="c1"># Point(x=11, y=22)</span>
<span class="c1"># 可以像元组一样通过下标访问元素，还可以通过字段名访问元素。</span>
<span class="nb">print</span><span class="p">(</span><span class="n">s1</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">s1</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
</code></pre></div>

<h4 id="shi-yong-lei-xing-zhu-jie-yu-fa-chuang-jian-ju-ming-yuan-zu"><a class="toclink" href="#shi-yong-lei-xing-zhu-jie-yu-fa-chuang-jian-ju-ming-yuan-zu">使用类型注解语法创建具名元组</a></h4>
<p>可以通过类型注解的typing.NamedTuple定义具名元组的类型。这种方式可读性更好：</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">NamedTuple</span>

<span class="k">class</span> <span class="nc">Student</span><span class="p">(</span><span class="n">NamedTuple</span><span class="p">):</span>
    <span class="n">name</span><span class="p">:</span> <span class="nb">str</span>
    <span class="n">age</span><span class="p">:</span> <span class="nb">int</span>
    <span class="n">gender</span><span class="p">:</span> <span class="nb">str</span>

<span class="n">s1</span> <span class="o">=</span> <span class="n">Student</span><span class="p">(</span><span class="s1">&#39;小明&#39;</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="s1">&#39;男&#39;</span><span class="p">)</span>
</code></pre></div>

<p>也能反向兼容collections.namedtuple的语法形式：</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">NamedTuple</span>

<span class="n">Student</span> <span class="o">=</span> <span class="n">NamedTuple</span><span class="p">(</span><span class="s1">&#39;Student&#39;</span><span class="p">,</span> <span class="p">[(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="nb">str</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;age&#39;</span><span class="p">,</span> <span class="nb">int</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;gender&#39;</span><span class="p">,</span> <span class="nb">str</span><span class="p">)])</span>
</code></pre></div>

<p>可以为字段提供默认值，支持文档字符串（docstring）与方法：</p>
<div class="highlight"><pre><span></span><code><span class="k">class</span> <span class="nc">Employee</span><span class="p">(</span><span class="n">NamedTuple</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Represents an employee.&quot;&quot;&quot;</span>
    <span class="n">name</span><span class="p">:</span> <span class="nb">str</span>
    <span class="nb">id</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">3</span>

    <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
        <span class="k">return</span> <span class="sa">f</span><span class="s1">&#39;&lt;Employee </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s1">, id=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s1">&gt;&#39;</span>

<span class="n">employee</span> <span class="o">=</span> <span class="n">Employee</span><span class="p">(</span><span class="s1">&#39;Guido&#39;</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">employee</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="mi">3</span>
</code></pre></div>

<h4 id="shu-xing-he-fang-fa"><a class="toclink" href="#shu-xing-he-fang-fa">属性和方法</a></h4>
<p>除了继承了普通元组之外，具名元组还有更多属性和方法:</p>
<ul>
<li>_fields类属性：包含了这个类所有字段名称的元组。  </li>
<li>_make(iterable) 类方法：通过接受一个可迭代对象来生成这个类的一个实例。另一种创建具名元组的方法。  </li>
<li>_asdict()实例方法：把具名元组以collections.OrderedDict的形式返回。可以把元组里的信息友好的呈现出来。  </li>
</ul>
<div class="highlight"><pre><span></span><code><span class="o">&gt;&gt;&gt;</span> <span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">Student</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s1">&#39;Student&#39;</span><span class="p">,</span> <span class="s1">&#39;name age gender&#39;</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">Student</span><span class="o">.</span><span class="n">_fields</span>
<span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;age&#39;</span><span class="p">,</span> <span class="s1">&#39;gender&#39;</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> 
<span class="o">&gt;&gt;&gt;</span> <span class="n">xiaoming</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;小明&#39;</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="s1">&#39;男&#39;</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">s1</span> <span class="o">=</span> <span class="n">Student</span><span class="o">.</span><span class="n">_make</span><span class="p">(</span><span class="n">xiaoming</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">s1</span>
<span class="n">Student</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;小明&#39;</span><span class="p">,</span> <span class="n">age</span><span class="o">=</span><span class="mi">14</span><span class="p">,</span> <span class="n">gender</span><span class="o">=</span><span class="s1">&#39;男&#39;</span><span class="p">)</span>
<span class="c1"># 作用和 Student(*xiaoming) 是一样的</span>
<span class="o">&gt;&gt;&gt;</span> 
<span class="o">&gt;&gt;&gt;</span> <span class="n">s1</span><span class="o">.</span><span class="n">_asdict</span><span class="p">()</span>
<span class="n">OrderedDict</span><span class="p">([(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;小明&#39;</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;age&#39;</span><span class="p">,</span> <span class="mi">14</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;gender&#39;</span><span class="p">,</span> <span class="s1">&#39;男&#39;</span><span class="p">)])</span>
<span class="o">&gt;&gt;&gt;</span> <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">s1</span><span class="o">.</span><span class="n">_asdict</span><span class="p">()</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">key</span><span class="o">+</span><span class="s1">&#39;:&#39;</span><span class="p">,</span><span class="n">value</span><span class="p">)</span>


<span class="n">name</span><span class="p">:</span> <span class="n">小明</span>
<span class="n">age</span><span class="p">:</span> <span class="mi">14</span>
<span class="n">gender</span><span class="p">:</span> <span class="n">男</span>
<span class="o">&gt;&gt;&gt;</span> 
</code></pre></div>

<h4 id="shi-yong-chang-jing"><a class="toclink" href="#shi-yong-chang-jing">使用场景</a></h4>
<p>增强可读性。使用普通元组可读性不强。<br>
通过定义一个类（class）也一样可以明确字段的含义，用具名元组更方便，更轻量（class的内存开销要大很多）。<br>
namedtuple（具名元组），继承了tuple良好的性能，又增加了可读性。<br>
相对于类，实现了属性的定义，但是不能像类一样定义方法。因此在考虑要定义一个类，但是类里不需要定义方法的时候，可以用namedtuple来代替。  </p>
<p>再多放一个具体的例子。下面是生成一副扑克牌（52张，没有大小王）的例子:</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>
<span class="c1"># 表示一张纸牌，有点数和花色</span>
<span class="n">Card</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s1">&#39;Card&#39;</span><span class="p">,</span> <span class="s1">&#39;rank suit&#39;</span><span class="p">)</span>
<span class="c1"># 定义了13个点数的列表</span>
<span class="n">ranks</span> <span class="o">=</span> <span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">11</span><span class="p">)]</span> <span class="o">+</span> <span class="nb">list</span><span class="p">(</span><span class="s1">&#39;JQKA&#39;</span><span class="p">)</span>
<span class="c1"># 定义了4种花色的列表</span>
<span class="n">suits</span> <span class="o">=</span> <span class="s1">&#39;spades diamonds clubs hearts&#39;</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
<span class="c1"># 列表生成式，遍历两个列表，生成所有的纸牌</span>
<span class="n">cards</span> <span class="o">=</span> <span class="p">[</span><span class="n">Card</span><span class="p">(</span><span class="n">rank</span><span class="p">,</span> <span class="n">suit</span><span class="p">)</span> <span class="k">for</span> <span class="n">suit</span> <span class="ow">in</span> <span class="n">suits</span> 
                          <span class="k">for</span> <span class="n">rank</span> <span class="ow">in</span> <span class="n">ranks</span><span class="p">]</span>
<span class="nb">print</span><span class="p">(</span><span class="n">cards</span><span class="p">)</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">[Card(rank=&#39;2&#39;, suit=&#39;spades&#39;), Card(rank=&#39;3&#39;, suit=&#39;spades&#39;), Card(rank=&#39;4&#39;, suit=&#39;spades&#39;), Card(rank=&#39;5&#39;, suit=&#39;spades&#39;), Card(rank=&#39;6&#39;, suit=&#39;spades&#39;), Card(rank=&#39;7&#39;, suit=&#39;spades&#39;), Card(rank=&#39;8&#39;, suit=&#39;spades&#39;), Card(rank=&#39;9&#39;, suit=&#39;spades&#39;), Card(rank=&#39;10&#39;, suit=&#39;spades&#39;), Card(rank=&#39;J&#39;, suit=&#39;spades&#39;), Card(rank=&#39;Q&#39;, suit=&#39;spades&#39;), Card(rank=&#39;K&#39;, suit=&#39;spades&#39;), Card(rank=&#39;A&#39;, suit=&#39;spades&#39;), </span>
<span class="sd">Card(rank=&#39;2&#39;, suit=&#39;diamonds&#39;), Card(rank=&#39;3&#39;, suit=&#39;diamonds&#39;), Card(rank=&#39;4&#39;, suit=&#39;diamonds&#39;), Card(rank=&#39;5&#39;, suit=&#39;diamonds&#39;), Card(rank=&#39;6&#39;, suit=&#39;diamonds&#39;), Card(rank=&#39;7&#39;, suit=&#39;diamonds&#39;), Card(rank=&#39;8&#39;, suit=&#39;diamonds&#39;), Card(rank=&#39;9&#39;, suit=&#39;diamonds&#39;), Card(rank=&#39;10&#39;, suit=&#39;diamonds&#39;), Card(rank=&#39;J&#39;, suit=&#39;diamonds&#39;), Card(rank=&#39;Q&#39;, suit=&#39;diamonds&#39;), Card(rank=&#39;K&#39;, suit=&#39;diamonds&#39;), Card(rank=&#39;A&#39;, suit=&#39;diamonds&#39;), </span>
<span class="sd">Card(rank=&#39;2&#39;, suit=&#39;clubs&#39;), Card(rank=&#39;3&#39;, suit=&#39;clubs&#39;), Card(rank=&#39;4&#39;, suit=&#39;clubs&#39;), Card(rank=&#39;5&#39;, suit=&#39;clubs&#39;), Card(rank=&#39;6&#39;, suit=&#39;clubs&#39;), Card(rank=&#39;7&#39;, suit=&#39;clubs&#39;), Card(rank=&#39;8&#39;, suit=&#39;clubs&#39;), Card(rank=&#39;9&#39;, suit=&#39;clubs&#39;), Card(rank=&#39;10&#39;, suit=&#39;clubs&#39;), Card(rank=&#39;J&#39;, suit=&#39;clubs&#39;), Card(rank=&#39;Q&#39;, suit=&#39;clubs&#39;), Card(rank=&#39;K&#39;, suit=&#39;clubs&#39;), Card(rank=&#39;A&#39;, suit=&#39;clubs&#39;), </span>
<span class="sd">Card(rank=&#39;2&#39;, suit=&#39;hearts&#39;), Card(rank=&#39;3&#39;, suit=&#39;hearts&#39;), Card(rank=&#39;4&#39;, suit=&#39;hearts&#39;), Card(rank=&#39;5&#39;, suit=&#39;hearts&#39;), Card(rank=&#39;6&#39;, suit=&#39;hearts&#39;), Card(rank=&#39;7&#39;, suit=&#39;hearts&#39;), Card(rank=&#39;8&#39;, suit=&#39;hearts&#39;), Card(rank=&#39;9&#39;, suit=&#39;hearts&#39;), Card(rank=&#39;10&#39;, suit=&#39;hearts&#39;), Card(rank=&#39;J&#39;, suit=&#39;hearts&#39;), Card(rank=&#39;Q&#39;, suit=&#39;hearts&#39;), Card(rank=&#39;K&#39;, suit=&#39;hearts&#39;), Card(rank=&#39;A&#39;, suit=&#39;hearts&#39;)]</span>
<span class="sd">&quot;&quot;&quot;</span>
</code></pre></div>

<h3 id="defaultdict"><a class="toclink" href="#defaultdict">defaultdict</a></h3>
<p>defaultdict是普通字典（dict）类型的子类。初始化时，可以给key指定默认值。  </p>
<h4 id="chuang-jian-defaultdict"><a class="toclink" href="#chuang-jian-defaultdict">创建defaultdict</a></h4>
<p>普通字典，访问一个不存在的key时会报错。如果是defaultdict，可以给不存在的key一个默认的初始值。<br>
下面分别是默认值为空列表和0的字典:</p>
<div class="highlight"><pre><span></span><code><span class="o">&gt;&gt;&gt;</span> <span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">defaultdict</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">d1</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">list</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">d1</span><span class="p">[</span><span class="s1">&#39;a&#39;</span><span class="p">]</span>
<span class="p">[]</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">d2</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">int</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">d2</span><span class="p">[</span><span class="s1">&#39;a&#39;</span><span class="p">]</span>
<span class="mi">0</span>
<span class="o">&gt;&gt;&gt;</span> 
</code></pre></div>

<p>这里设置的默认值不是一个具体的值，defaultdict函数接收的参数是一个可调用对象。<br>
list和int是数据类型，同时也是一个函数，list()的返回值是一个空列表，int()的返回值是0。  </p>
<p>如果希望默认值是一个具体的值，比如数值1，可以使用匿名函数:</p>
<div class="highlight"><pre><span></span><code><span class="o">&gt;&gt;&gt;</span> <span class="n">d3</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="k">lambda</span> <span class="p">:</span> <span class="mi">1</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">d3</span><span class="p">[</span><span class="s1">&#39;a&#39;</span><span class="p">]</span>
<span class="mi">1</span>
<span class="o">&gt;&gt;&gt;</span> 
</code></pre></div>

<p>当然自定义的函数也是可以的:</p>
<div class="highlight"><pre><span></span><code><span class="o">&gt;&gt;&gt;</span> <span class="k">def</span> <span class="nf">v2</span><span class="p">():</span>
    <span class="k">return</span> <span class="mi">2</span>

<span class="o">&gt;&gt;&gt;</span> <span class="n">d4</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="n">v2</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">d4</span><span class="p">[</span><span class="s1">&#39;a&#39;</span><span class="p">]</span>
<span class="mi">2</span>
<span class="o">&gt;&gt;&gt;</span> 
</code></pre></div>

<h4 id="shi-yong-chang-jing_1"><a class="toclink" href="#shi-yong-chang-jing_1">使用场景</a></h4>
<p>当字典<code>d[key]</code>找不到key的时候，会抛出异常。可以用<code>d.get(key, default)</code>来替代，也能获得一个默认值。<br>
用来获取字典的值，这样做就足够好了。但是如果是要<strong>更新字典的值</strong>，这就不是一个好的方法，效率低。  </p>
<p><strong>准备示例使用的文本</strong><br>
下面的例子对“python之禅”做单词的统计。可以通过如下命令先生成一个txt文件:</p>
<div class="highlight"><pre><span></span><code>python -m this &gt; zen.txt
</code></pre></div>

<p><strong>编码问题</strong>，可能导出的文件是系统平台的默认编码，不是utf-8。那就还需要打开文件用utf-8的编码在保存一下。<br>
当然也可以统计任意的文本文件。  </p>
<h5 id="yong-zi-dian-de-get-huo-qu-mo-ren-zhi-bu-tui-jian"><a class="toclink" href="#yong-zi-dian-de-get-huo-qu-mo-ren-zhi-bu-tui-jian">用字典的get获取默认值（不推荐）</a></h5>
<p>首先是一个不好的实现:</p>
<div class="highlight"><pre><span></span><code><span class="sd">&quot;&quot;&quot;创建一个从单词到其出现情况的映射&quot;&quot;&quot;</span>

<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">re</span>

<span class="n">WORD_RE</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;\w+&#39;</span><span class="p">)</span>

<span class="n">index</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">fp</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">line_no</span><span class="p">,</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="mi">1</span><span class="p">):</span>   <span class="c1"># 遍历行号和每一行的内容，行号从1开始</span>
        <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">WORD_RE</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
            <span class="n">word</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">()</span>
            <span class="n">column_no</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">start</span><span class="p">()</span><span class="o">+</span><span class="mi">1</span>      <span class="c1"># 单词出现的列，列号也从1开始</span>
            <span class="n">location</span> <span class="o">=</span> <span class="p">(</span><span class="n">line_no</span><span class="p">,</span> <span class="n">column_no</span><span class="p">)</span>  <span class="c1"># 单词出现的行号和列号</span>
            <span class="c1"># 一个不好的实现，用字典的get解决key值不存在时的默认值</span>
            <span class="n">occurences</span> <span class="o">=</span> <span class="n">index</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">word</span><span class="p">,</span> <span class="p">[])</span> <span class="c1"># 1次字典的查询</span>
            <span class="n">occurences</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">location</span><span class="p">)</span>
            <span class="n">index</span><span class="p">[</span><span class="n">word</span><span class="p">]</span> <span class="o">=</span> <span class="n">occurences</span>         <span class="c1"># 2次字典的查询 </span>
<span class="c1"># 以字母顺序打印结果</span>
<span class="k">for</span> <span class="n">word</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="nb">str</span><span class="o">.</span><span class="n">upper</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">word</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">index</span><span class="p">[</span><span class="n">word</span><span class="p">]),</span> <span class="n">index</span><span class="p">[</span><span class="n">word</span><span class="p">])</span>
</code></pre></div>

<p><strong>效率低</strong>，上面的示例中有2次字典的查询。优化后只要1次。  </p>
<p>执行后，显示的结果大概是这样的:</p>
<div class="highlight"><pre><span></span><code>$ python demo1.py zen.txt
a 2 [(19, 48), (20, 53)]
Although 3 [(11, 1), (16, 1), (18, 1)]
ambiguity 1 [(14, 16)]
and 1 [(15, 23)]
are 1 [(21, 12)]
aren 1 [(10, 15)]
at 1 [(16, 38)]
......
</code></pre></div>

<p>每一行一个单词，然后是出现的次数，最后是一个列表，记录单词出现的位置(行号, 列号)。  </p>
<h5 id="shi-yong-defaultdict"><a class="toclink" href="#shi-yong-defaultdict">使用defaultdict</a></h5>
<p>使用defaultdict，可以帮助我们处理不存在的key的情况。<br>
下面是优化后的例子，保留注释了优化前的代码:</p>
<div class="highlight"><pre><span></span><code><span class="sd">&quot;&quot;&quot;创建一个从单词到其出现情况的映射&quot;&quot;&quot;</span>

<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">defaultdict</span>

<span class="n">WORD_RE</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;\w+&#39;</span><span class="p">)</span>

<span class="c1">#index = {}</span>
<span class="n">index</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">list</span><span class="p">)</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">fp</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">line_no</span><span class="p">,</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="mi">1</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">WORD_RE</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
            <span class="n">word</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">()</span>
            <span class="n">column_no</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">start</span><span class="p">()</span><span class="o">+</span><span class="mi">1</span>
            <span class="n">location</span> <span class="o">=</span> <span class="p">(</span><span class="n">line_no</span><span class="p">,</span> <span class="n">column_no</span><span class="p">)</span>
            <span class="c1">#occurences = index.get(word, [])</span>
            <span class="c1">#occurences.append(location)</span>
            <span class="c1">#index[word] = occurences</span>
            <span class="n">index</span><span class="p">[</span><span class="n">word</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">location</span><span class="p">)</span>

<span class="c1"># 以字母顺序打印结果</span>
<span class="k">for</span> <span class="n">word</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="nb">str</span><span class="o">.</span><span class="n">upper</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">word</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">index</span><span class="p">[</span><span class="n">word</span><span class="p">]),</span> <span class="n">index</span><span class="p">[</span><span class="n">word</span><span class="p">])</span>
</code></pre></div>

<h5 id="shi-yong-dictsetdefault"><a class="toclink" href="#shi-yong-dictsetdefault">使用 dict.setdefault</a></h5>
<p>除了defaultdict，这里的方法也是推荐使用的。<br>
这里用dict.setdefault，如果key存在则取出value，如果key不存在，为key设置好默认value后把value取出。<br>
在上面的例子中，将最内侧的for循环里最后一句替换掉，并且继续使用默认的字典:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># 继续使用默认的字典</span>
<span class="n">index</span> <span class="o">=</span> <span class="p">{}</span>

            <span class="c1">#index[word].append(location)</span>
            <span class="n">index</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">wodr</span><span class="p">,</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">location</span><span class="p">)</span>
</code></pre></div>

<p>这里还比较好理解，调用append之前先将列表取出。使用key来获取列表，如果key不存在，则先为key设置好默认值再取出。<br>
defaultdict 是在类里实现了默认值的设置。整个类的默认值都是一样的。<br>
dict.setdefault 是调用字典的方法，完成设置默认值并取值。默认值在每次调用的时候都可以指定。  </p>
<h5 id="xiao-jie"><a class="toclink" href="#xiao-jie">小结</a></h5>
<p>下面几种写法的效果是一样的:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># 推荐方法一，定义有默认值的字典</span>
<span class="n">my_dict</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">list</span><span class="p">)</span>
<span class="n">my_dict</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">new_value</span><span class="p">)</span>

<span class="c1"># 推荐方法二，取值的同时，如果key不存在，先为key设置好默认值</span>
<span class="n">my_dict</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">new_value</span><span class="p">)</span>

<span class="c1"># 效果一样，但不推荐</span>
<span class="k">if</span> <span class="n">key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">my_dict</span><span class="p">:</span>  <span class="c1"># 第一次字典的查询</span>
    <span class="n">my_dict</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>   <span class="c1"># 如果key不存在，再一次字典的查询 </span>
<span class="n">my_dict</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">new_value</span><span class="p">)</span>  <span class="c1"># 第二次，如果key不存在是第三次字典的查询</span>
</code></pre></div>

<p>之前说的2次查询，这里变成了3次。因为之前用了字典的get方法，get方法本身优化了一次字典查询不存在的情况。适用于字典查询的场景。<br>
get方法的第二个参数也是默认值，但只是返回值，不会为字典添加key并设置value。<br>
对于要<strong>更新字典的值</strong>，就应该使用这里讲的2个方法，只要一次字典的查询就能完成。  </p>
<h3 id="counter"><a class="toclink" href="#counter">Counter</a></h3>
<p>Counter也是dict的子类，它的作用是用于统计计数。这个类型会给key准备一个计数器，每次更新一个key的时候，都会增加计数。<br>
这个类型可以用来给对象计数，key是元素，value是每个元素的计数。<br>
还可以当成多重集来用：集合里的元素可以出现不止一次。  </p>
<p>统计字符串中字母出现的次数:</p>
<div class="highlight"><pre><span></span><code><span class="o">&gt;&gt;&gt;</span> <span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">Counter</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">ct</span> <span class="o">=</span> <span class="n">Counter</span><span class="p">(</span><span class="s1">&#39;hello&#39;</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">ct</span>
<span class="n">Counter</span><span class="p">({</span><span class="s1">&#39;l&#39;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="s1">&#39;h&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;e&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;o&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">})</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">ct</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="s1">&#39;world&#39;</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">ct</span>
<span class="n">Counter</span><span class="p">({</span><span class="s1">&#39;l&#39;</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="s1">&#39;o&#39;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="s1">&#39;h&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;e&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;w&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;r&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;d&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">})</span>
</code></pre></div>

<p>most_common(n)方法，返回前n个出现次数最多的元素:</p>
<div class="highlight"><pre><span></span><code><span class="o">&gt;&gt;&gt;</span> <span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">Counter</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">colors</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;red&#39;</span><span class="p">,</span> <span class="s1">&#39;blue&#39;</span><span class="p">,</span> <span class="s1">&#39;red&#39;</span><span class="p">,</span> <span class="s1">&#39;green&#39;</span><span class="p">,</span> <span class="s1">&#39;blue&#39;</span><span class="p">,</span> <span class="s1">&#39;blue&#39;</span><span class="p">]</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">ct2</span> <span class="o">=</span> <span class="n">Counter</span><span class="p">(</span><span class="n">colors</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">ct2</span>
<span class="n">Counter</span><span class="p">({</span><span class="s1">&#39;blue&#39;</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="s1">&#39;red&#39;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="s1">&#39;green&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">})</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">ct2</span><span class="o">.</span><span class="n">most_common</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="p">[(</span><span class="s1">&#39;blue&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;red&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)]</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">ct2</span><span class="o">.</span><span class="n">most_common</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="p">[(</span><span class="s1">&#39;blue&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">)]</span>
</code></pre></div>

<p><strong>统计字数</strong><br>
继续对文本做字数的统计，这次用Counter只做频率的统计:</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">Counter</span>

<span class="n">WORD_RE</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;\w+&#39;</span><span class="p">)</span>

<span class="n">index</span> <span class="o">=</span> <span class="n">Counter</span><span class="p">()</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">fp</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">fp</span><span class="p">:</span>
        <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">WORD_RE</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
            <span class="n">word</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">()</span>
            <span class="n">index</span><span class="o">.</span><span class="n">update</span><span class="p">([</span><span class="n">word</span><span class="p">])</span>

<span class="nb">print</span><span class="p">(</span><span class="n">index</span><span class="o">.</span><span class="n">most_common</span><span class="p">(</span><span class="mi">2</span><span class="p">))</span>
<span class="k">for</span> <span class="n">word</span><span class="p">,</span> <span class="n">count</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">index</span><span class="o">.</span><span class="n">items</span><span class="p">(),</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">upper</span><span class="p">()):</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">word</span><span class="p">,</span> <span class="n">count</span><span class="p">)</span>
</code></pre></div>

<p>这里注意，update方法提供的参数也是要进行迭代的。如果直接给字符串，则会对字符串进行迭代，一个字符一个字符添加到Counter中。这里把字符串放到了列表中作为参数。  </p>
<p>执行后的结果，可以和之前的例子比较下:</p>
<div class="highlight"><pre><span></span><code>[(&#39;is&#39;, 10), (&#39;better&#39;, 8)]
a 2
Although 3
ambiguity 1
and 1
are 1
aren 1
at 1
......
</code></pre></div>

<h3 id="qi-ta-lei-xing"><a class="toclink" href="#qi-ta-lei-xing">其他类型</a></h3>
<p>在标准库的collections中，还有一些其他类型，主要都是dict的子类，映射类型。  </p>
<p><strong>collections.OrderedDict</strong><br>
在添加key的时候，会保持顺序。从Python3.7开始，字典已经有了这种特性了。所以用处不大了，但是这个类型还一直存在，与原生字典还是有一些区别的。<br>
对于两个键值对相同，但是顺序不同的字典。原始字典的比较结果是True，而OrderedDict的比较结果是False。<br>
提供了如<code>move_to_end</code>方法，原始字典没有这类方法。  </p>
<p><strong>collections.ChainMap</strong><br>
这个类型可以容纳数个不同的映射对象，然后在进行key查找的操作时，会被当做一个整体被逐个查找，直到key被找到为止。<br>
相当于把多个字典合并到一起。普通的字典合并后会并成一个字典。这里的方法合并后每个字典还是独立的，并且也能获取到所有的元素。  </p>
<p>示例代码，Python变量查询规则:</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">ChainMap</span>
<span class="kn">import</span> <span class="nn">builtins</span>
<span class="n">pylookup</span> <span class="o">=</span> <span class="n">ChainMap</span><span class="p">(</span><span class="nb">locals</span><span class="p">(),</span> <span class="nb">globals</span><span class="p">(),</span> <span class="nb">vars</span><span class="p">(</span><span class="n">builtins</span><span class="p">))</span>
</code></pre></div>

<h3 id="userdict"><a class="toclink" href="#userdict">UserDict</a></h3>
<p>其实就是把标准的dict用纯Python又实现了一遍。<br>
这个最后讲，只有这个类型不是开箱即用的，而是让用户继承写子类的。<br>
如果要创造一个自定义字典类型，以UserDict为基类，总比以dict为基类要来的方便。<br>
子类化内置类型很麻烦，内置类型使用C语言编写，不会调用用户定义的类覆盖的特殊方法。  </p>
<p>自定义字典，无论是添加、更新还是查询操作，都会把非字符串的key转换为字符串:</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">collections</span>

<span class="k">class</span> <span class="nc">StrKeyDict</span><span class="p">(</span><span class="n">collections</span><span class="o">.</span><span class="n">UserDict</span><span class="p">):</span>

    <span class="k">def</span> <span class="fm">__missing__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> 
        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
            <span class="k">raise</span> <span class="ne">KeyError</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
        <span class="k">return</span> <span class="bp">self</span><span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">key</span><span class="p">)]</span>

    <span class="k">def</span> <span class="fm">__contains__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
        <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">key</span><span class="p">)</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span>

    <span class="k">def</span> <span class="fm">__setitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">item</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">key</span><span class="p">)]</span> <span class="o">=</span> <span class="n">item</span>
</code></pre></div>
      </div>
      <div class="back-to-top">
        <a href="/">HOME</a>
        <a href="#top">TOP</a>
      </div>
    </article>
  </div>
<!-- end article -->
<!-- 页面往下滚动一段之后才会显示TOC -->
<script>
  window.onscroll = function() {
    var tocbox = document.getElementsByClassName('toc')[0];
    var osTop = document.documentElement.scrollTop || document.body.scrollTop;
    var osWidth = document.documentElement.scrollWidth || document.body.scrollWidth;
    // console.log(osTop)
    if (osTop>300 && osWidth>865) {
      tocbox.style.display = "block"
    }
    if (osTop<300 || osWidth<865) {
      tocbox.style.display = "none"
    }
  }
</script>
                <footer>
                    <div class="icons">
                    </div>
                    <span id="busuanzi_container_page_pv" style="padding: 10px">本文阅读量<span id="busuanzi_value_page_pv"></span>次</span>
                    <span id="busuanzi_container_site_pv" style="padding: 10px">本站总访问量<span id="busuanzi_value_site_pv"></span>次</span>
                    <span id="busuanzi_container_site_uv" style="padding: 10px">本站总访客数<span id="busuanzi_value_site_uv"></span>人</span>
                    <p>© <script>document.write(moment().format('YYYY'));</script> 749B</p>
                </footer>
        </div>
</body>
</html>